/*
defer
https://golang.google.cn/blog/defer-panic-and-recover
*/
package main

import "fmt"

type T struct {
	a int
}

func (i *T) set(a int) *T {
	fmt.Print(a)
	i.a = a
	return i
}

func main() {
	fmt.Println("=====defer1=====")
	defer1()
	defer1a()

	fmt.Println()
	fmt.Println("=====defer2=====")
	defer2()

	fmt.Println("=====defer3=====")
	fmt.Println(defer3())
	fmt.Println(defer3a(3))

}

/*
规则一 当defer被声明时，其参数就会被实时解析
输出
x
2 result= 8
1 result= 4
*/
func defer1() {
	var i = 1
	defer fmt.Println("1 result=",
		func() int {
			fmt.Println("x")
			i++
			return i * 2
		}())
	i++

	defer func() {
		fmt.Println("2 result=", i*2)
	}()
	i++
}

/**
输出
1234
*/
func defer1a() {
	var t T
	defer t.set(1).set(2).set(4)
	t.set(3)
}

/*
规则二 defer执行顺序为先进后出
Hello World !!!
*/
func defer2() {
	defer fmt.Println("!!!")
	defer fmt.Print("World ")
	fmt.Print("Hello ")
}

/*
规则三 defer可以读取有名返回值
返回2
*/
func defer3() (i int) {
	defer func() { i++ }()
	return 1
}

// 返回7
func defer3a(n int) (r int) {
	defer func() {
		r += n
	}()

	return n + 1
}
